/*************************************************************************
Crytek Source File.
Copyright (C) 2011, Crytek Studios
-------------------------------------------------------------------------
History:
- 04:08:2011		Created by Will Wilson
*************************************************************************/

#pragma once

#ifndef __SOFTCODEMGR_H__
#define __SOFTCODEMGR_H__

#include <CryListenerSet.h>

#include "ISoftCodeMgr.h"

struct ITypeLibrary;
struct ITypeRegistrar;
class CExchanger;

// Internal: Performs the dynamic type management needed for SoftCoding
class DynamicTypeLibrary : public ITypeLibrary
{
public:
	DynamicTypeLibrary(const char* name = NULL);

	// ITypeLibrary impl.
	virtual const char* GetName();
	virtual bool CreateInstance(const char* typeName, void** ppInstance);
	virtual void SetOverride(ITypeLibrary* pOverrideLib);
	virtual size_t GetTypes(ITypeRegistrar** ppRegistrar, size_t& count) const;

	void AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName);
	void RemoveListener(ISoftCodeListener* pListener);

	// Attempts to add the library types the active set
	void IntegrateLibrary(ITypeLibrary* pLib, bool isDefault);

private:
	// Attempts to add the type the active set
	void IntegrateType(ITypeRegistrar* pType, bool isDefault);
	// Ensure the type can be safely created, visited, destroyed and prep exchanger
	bool EvaluateType(ITypeRegistrar* pType, CExchanger& exchanger);

private:
	typedef std::vector<ITypeLibrary*> TLibVec;
	typedef std::map<string, ITypeRegistrar*> TTypeMap;
	typedef CListenerSet<ISoftCodeListener*> TListeners;

	// The current set of active types
	std::map<string, ITypeRegistrar*> m_types;
	// Current set of loaded libraries
	TLibVec m_history;
	// Set of listeners to SC changes
	TListeners m_listeners;

	const char* m_name;		// Supplied by the first real library that registers
};


// Implements the global singleton responsible for SoftCode management
class SoftCodeMgr : public ISoftCodeMgr
{
public:
	SoftCodeMgr();
	virtual ~SoftCodeMgr();
	
	// Used to register built-in libraries on first use
	virtual void RegisterLibrary(ITypeLibrary* pLib);

	// Look for new SoftCode modules and load them, adding their types to the registry
	virtual void LoadNewModules();

	virtual void AddListener(const char* libraryName, ISoftCodeListener* pListener, const char* listenerName);
	virtual void RemoveListener(const char* libraryName, ISoftCodeListener* pListener);

	// To be called regularly to poll for library updates
	virtual void PollForNewModules();

private:
	size_t FindSoftCodeFiles(const string& searchName, std::vector<string>& foundPaths) const;
	
private:
	typedef std::map<string, DynamicTypeLibrary> TLibMap;
	typedef std::set<string> TLoadedLibSet;
	
	// Records the history for each TypeLibrary keyed by library name
	TLibMap m_libraryMap;
	
	// Records the library files already loaded
	TLoadedLibSet m_loadedSet;

	// Used to determine when the next auto-update will occur
	CTimeValue m_nextAutoCheckTime;
};


#endif
